package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.domain.AccountLog;
import cn.wolfcode.domain.AccountTransaction;
import cn.wolfcode.domain.OperateIntergralVo;
import cn.wolfcode.domain.UsableIntegral;
import cn.wolfcode.mapper.AccountLogMapper;
import cn.wolfcode.mapper.AccountTransactionMapper;
import cn.wolfcode.mapper.UsableIntegralMapper;
import cn.wolfcode.service.IUsableIntegralService;
import cn.wolfcode.web.msg.IntergralCodeMsg;
import com.alibaba.fastjson.JSON;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import java.util.Date;


@Service
@Slf4j
public class UsableIntegralServiceImpl implements IUsableIntegralService {
    @Autowired
    private UsableIntegralMapper usableIntegralMapper;
    @Autowired
    private AccountTransactionMapper accountTransactionMapper;
    @Autowired
    private AccountLogMapper accountLogMapper;

    @Override
    @Transactional
    public void descIntergral(OperateIntergralVo operateIntergralVo) {
        //往日志表插入数据
        AccountLog accountLog = new AccountLog();
        accountLog.setPkValue(operateIntergralVo.getPk());
        accountLog.setType(AccountLog.TYPE_DECR);
        accountLog.setGmtTime(new Date());
        accountLog.setInfo(operateIntergralVo.getInfo());
        accountLog.setAmount(operateIntergralVo.getValue());
        accountLogMapper.insert(accountLog);
        //减少积分
        //根据订单id更新积分
        int count = usableIntegralMapper.descIntergral(operateIntergralVo.getUserId(), operateIntergralVo.getValue());
        if(count == 0){
            throw new BusinessException(IntergralCodeMsg.INTERGRAL_NOT_ENOUGH);
        }
    }

    @Override
    @Transactional
    public void incrIntergral(OperateIntergralVo operateIntergralVo) {
        //插入流水记录
        AccountLog accountLog = new AccountLog();
        accountLog.setPkValue(operateIntergralVo.getPk());
        accountLog.setType(AccountLog.TYPE_INCR);
        accountLog.setAmount(operateIntergralVo.getValue());
        accountLog.setGmtTime(new Date());
        accountLog.setInfo(operateIntergralVo.getInfo());
        accountLogMapper.insert(accountLog);
        //加积分
        usableIntegralMapper.addIntergral(operateIntergralVo.getUserId(),operateIntergralVo.getValue());
    }





    /*-----------------------------------------积分支付-------------------------------------------------------*/

    @Override
    public void decrIntergralTry(OperateIntergralVo operateIntergralVo, BusinessActionContext context) {
        log.info("进入try方法");
        this.commonSaveAccountTransaction(operateIntergralVo,context,AccountTransaction.STATE_TRY,AccountTransaction.DECR_TYPE);
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), context.getBranchId() + "");
        if(accountTransaction == null){
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
        //检查余额,如果积分不够，需要进行提示积分不足
        UsableIntegral usableIntegral = usableIntegralMapper.selectOneByOrderNo(accountTransaction.getUserId());
        if(usableIntegral.getAmount() < operateIntergralVo.getValue()){
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
        //扣除其中30积分，可用金额为账户金额-30，,冻结金额+30
        usableIntegralMapper.freezeIntergral(operateIntergralVo.getUserId(),operateIntergralVo.getValue());
    }

    @Override
    public void decrIntergralCommit(BusinessActionContext context) {
        log.info("进入commit方法");
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), context.getBranchId() + "");
        if(accountTransaction == null){
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }

        if(AccountTransaction.STATE_TRY.equals(accountTransaction.getState())){
            OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo1").toString(), OperateIntergralVo.class);
            //执行confirm业务逻辑
            //可用金额为账户金额-30，冻结金额-30
            usableIntegralMapper.commitChange(operateIntergralVo.getUserId(),operateIntergralVo.getValue());
            //把初始化状态修改为已提交状态
            accountTransactionMapper.updateAccountTransactionState(context.getXid(),context.getBranchId() + "",AccountTransaction.STATE_COMMIT,AccountTransaction.STATE_TRY);
        }else if(AccountTransaction.STATE_COMMIT.equals(accountTransaction.getState())){
            //不做任何操作，保证幂等性
        }else{
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }

    }

    @Override
    public void decrIntergralRollback(BusinessActionContext context) {
        log.info("进入cancal方法");
        //如果try出现异常等问题，需要进行回滚，将冻结金额-30
        OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), context.getBranchId() + "");
        if(accountTransaction == null){
            //往表中插入数据
            //防止try方法由于网络等原因执行比较慢超时了，TC会调用cancel，这样当try执行横沟后，由于cancel已经执行完了，导致try的资源无法释放
            this.commonSaveAccountTransaction(operateIntergralVo,context,AccountTransaction.STATE_CANCEL,AccountTransaction.DECR_TYPE);
        }
        if(AccountTransaction.STATE_TRY.equals(accountTransaction.getState())){
            //将冻结金额-30
            usableIntegralMapper.unFreezeIntergral(operateIntergralVo.getUserId(),operateIntergralVo.getValue());
            //将初始化状态改为已回滚状态
            accountTransactionMapper.updateAccountTransactionState(context.getXid(),context.getBranchId() + "",AccountTransaction.STATE_CANCEL,AccountTransaction.STATE_TRY);
        }else if(AccountTransaction.STATE_COMMIT.equals(accountTransaction.getState())){
            //不做任何操作保证幂等性
        }else{
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }


    }




    /*-----------------------------------------积分退款-------------------------------------------------------*/




    @Override
    public void incrIntergralTry(OperateIntergralVo operateIntergralVo, BusinessActionContext context) {
        log.info("进入try方法");
        this.commonSaveAccountTransaction(operateIntergralVo,context,AccountTransaction.STATE_TRY,AccountTransaction.INCR_TYPE);
    }

    @Override
    public void incrIntergralCommit(BusinessActionContext context) {
        log.info("进入commit方法");
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), context.getBranchId() + "");
        if(accountTransaction == null){
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
        if(AccountTransaction.STATE_TRY.equals(accountTransaction.getState())){
            OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
            //执行confirm逻辑
            //1.增加积分
            usableIntegralMapper.addIntergral(operateIntergralVo.getUserId(),operateIntergralVo.getValue());
            //2.把初始化状态修改为已提交状态
            accountTransactionMapper.updateAccountTransactionState(context.getXid(),context.getBranchId() + "",AccountTransaction.STATE_COMMIT,AccountTransaction.STATE_TRY);
        }else if(AccountTransaction.STATE_COMMIT.equals(accountTransaction.getState())){
            //不做任何操作保证幂等性
        }else{
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
    }

    public void commonSaveAccountTransaction(OperateIntergralVo operateIntergralVo, BusinessActionContext context, int state,String type){
        AccountTransaction accountTransaction = new AccountTransaction();
        accountTransaction.setTxId(context.getXid());
        accountTransaction.setActionId(context.getBranchId() + "");
        accountTransaction.setGmtCreated(new Date());
        accountTransaction.setGmtModified(new Date());
        accountTransaction.setAmount(operateIntergralVo.getValue());
        accountTransaction.setUserId(operateIntergralVo.getUserId());
        accountTransaction.setType(type);
        accountTransaction.setState(state);
        accountTransactionMapper.insert(accountTransaction);
    }

    @Override
    public void incrIntergralRollback(BusinessActionContext context) {
        log.info("进入cancal方法");
        OperateIntergralVo operateIntergralVo = JSON.parseObject(context.getActionContext("operateIntergralVo").toString(), OperateIntergralVo.class);
        AccountTransaction accountTransaction = accountTransactionMapper.get(context.getXid(), context.getBranchId() + "");
        if(accountTransaction == null){
            //往表中插入数据
            this.commonSaveAccountTransaction(operateIntergralVo,context,AccountTransaction.STATE_CANCEL,AccountTransaction.INCR_TYPE);
        }

        if(AccountTransaction.STATE_TRY.equals(accountTransaction.getState())){
            //执行cancel逻辑
            //把状态修改为已回滚状态
            accountTransactionMapper.updateAccountTransactionState(context.getXid(),context.getBranchId() +"",AccountTransaction.STATE_CANCEL,AccountTransaction.STATE_TRY);
        }else if(AccountTransaction.STATE_COMMIT.equals(accountTransaction.getState())){
            //不做任何操作保证幂等性
        }else{
            throw new BusinessException(IntergralCodeMsg.OP_INTERGRAL_ERROR);
        }
    }
}
